package com.dcits.electronic_account.service.impl;

import com.dcits.electronic_account.bean.LoginRecord;
import com.dcits.electronic_account.bean.VirtualAccount;
import com.dcits.electronic_account.mapper.LoginMapper;
import com.dcits.electronic_account.service.LoginService;
import com.dcits.electronic_account.utils.JwtUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.print.DocFlavor;
import java.math.BigDecimal;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import static com.dcits.electronic_account.utils.DateStampUtil.dateToString;
import static com.dcits.electronic_account.utils.LegalStringCheckUtil.legalStringCheck;
import static com.dcits.electronic_account.utils.MD5Util.getMd5;
import static com.dcits.electronic_account.utils.VerificationCodeUtil.*;

/**
 * @Author: CZJ
 * @Date： 2022/6/24
 */

@Service
@Log4j2
public class LoginServiceImpl implements LoginService {

    @Autowired
    LoginMapper loginMapper;

    @Autowired
    private JwtUtils jwtUtils;

    /**
     * @func 使用用户名和登录密码进行登录（业务实现）
     * @param virtualAccount
     * @return userId、userName、token
     */
    @Override
    public HashMap<String, Object> loginByUserName(VirtualAccount virtualAccount) {
        HashMap<String, Object> result = new HashMap<>();
        if(!StringUtils.isEmpty(virtualAccount.getUserName()) && !StringUtils.isEmpty(virtualAccount.getLoginPwd())){

            // 对登录密码进行MD5加密
            virtualAccount.setLoginPwd(getMd5(virtualAccount.getLoginPwd()));

            // 验证数据库是否存在该用户名和登录密码是否正确
            VirtualAccount res = loginMapper.loginByUserName(virtualAccount);
            if (res == null) return null;
            HashMap<String, String> temp = new HashMap<>();
            temp.put("userId", res.getUserId().toString());
            temp.put("userName", res.getUserName());

            // 新增一条登录记录
            LoginRecord loginRecord = new LoginRecord();
            loginRecord.setUserId(res.getUserId());
            loginRecord.setLoginTime(dateToString(new Date()));
            loginRecord.setState(1);
            loginMapper.addLoginRecord(loginRecord);

            // 封装userId进token，并返回userId、userName、token
            String token = jwtUtils.generateToken(String.valueOf(res.getUserId()));
            System.out.println("userId：" + res.getUserId());
            System.out.println("token：" + token);
            result.put("userInfo", temp);
            result.put("token", token);

            return result;
        }
        return null;
    }

    /**
     * @func 使用手机号登录（业务实现）
     * @param virtualAccount
     * @return
     */
    @Override
    public HashMap<String, Object> loginByPhone(VirtualAccount virtualAccount) {
        HashMap<String, Object> result = new HashMap<>();
        if(!StringUtils.isEmpty(virtualAccount.getPhone()) && !StringUtils.isEmpty(virtualAccount.getVerificationCode())){

            // 验证数据库中是否存在该手机号
            VirtualAccount res = loginMapper.loginByPhone(virtualAccount);
            if (res == null) return null;

            // 验证输入的验证码是否在有效期内且正确
            if (!verificationCodeValidate(virtualAccount.getPhone(), virtualAccount.getVerificationCode())) return null;

            HashMap<String, String> temp = new HashMap<>();
            temp.put("userId", res.getUserId().toString());
            temp.put("userName", res.getUserName());

            // 新增一条登录记录
            LoginRecord loginRecord = new LoginRecord();
            loginRecord.setUserId(res.getUserId());
            loginRecord.setLoginTime(dateToString(new Date()));
            loginRecord.setState(1);
            loginMapper.addLoginRecord(loginRecord);

            // 封装userId进token，并返回userId、userName、token
            String token = jwtUtils.generateToken(String.valueOf(res.getUserId()));
            result.put("userInfo", temp);
            result.put("token", token);

            return result;
        }
        return null;
    }

    /**
     * @func 在控制台上显示验证码
     * @param virtualAccount
     * @return
     */
    @Override
    public boolean getVerificationCode(VirtualAccount virtualAccount) {
        if (!StringUtils.isEmpty(virtualAccount.getPhone())){
            if (verificationCodeExist(virtualAccount.getPhone())){
                return false;
            }
            String verificationCode = generateVerificationCode(virtualAccount.getPhone());
            log.info("【神州信息】发送至" + virtualAccount.getPhone() + ", 登录验证码：" + verificationCode + ", 有效期60秒, 如非本人操作，请忽略此短信。" + dateToString(new Date()));
            return true;
        }
        return false;
    }

    /**
     * @func 用户注册（业务实现）
     * @param virtualAccount
     * @return
     */
    @Override
    public HashMap<Boolean, String> register(VirtualAccount virtualAccount) {
        HashMap<Boolean, String> res = new HashMap<>();

        // 对传入的参数进行判空
        if (!StringUtils.isEmpty(virtualAccount.getUserName()) && !StringUtils.isEmpty(virtualAccount.getLoginPwd())
        && !StringUtils.isEmpty(virtualAccount.getPayPwd()) && !StringUtils.isEmpty(virtualAccount.getCardType())
        && !StringUtils.isEmpty(virtualAccount.getIdNumber()) && !StringUtils.isEmpty(virtualAccount.getPhone())
        && !StringUtils.isEmpty(virtualAccount.getName()) && !StringUtils.isEmpty(virtualAccount.getVerificationCode())){
            virtualAccount.setRegisterTime(dateToString(new Date()));
            virtualAccount.setBalance(BigDecimal.valueOf(0));

            // 非法字符检测
            boolean b1 = legalStringCheck(virtualAccount.getUserName());
            boolean b2 = legalStringCheck(virtualAccount.getLoginPwd());
            boolean b3 = legalStringCheck(virtualAccount.getPayPwd());
            boolean b4 = legalStringCheck(virtualAccount.getIdNumber());
            boolean b5 = legalStringCheck(virtualAccount.getMail());
            boolean b6 = legalStringCheck(virtualAccount.getName());
            boolean b7 = legalStringCheck(virtualAccount.getAddress());
            boolean b8 = legalStringCheck(virtualAccount.getPhone());
            if (!b1 || !b2 || !b3 || !b4 || !b5 || !b6 || !b7 || !b8){
                res.put(false, "所填信息中存在非法字符，请检查！");
                return res;
            }

            // 验证数据库中该用户名是否已注册
            String userName = loginMapper.userNameExist(virtualAccount);
            if (!StringUtils.isEmpty(userName)){
                res.put(false, "该用户已存在！");
                return res;
            }

            // 验证数据库中该手机号是否已注册
            String phone = loginMapper.phoneExist(virtualAccount);
            if (!StringUtils.isEmpty(phone)){
                res.put(false, "该手机号已注册！");
                return res;
            }

            // 验证数据库中该身份证是否已注册
            String idNumber = loginMapper.idNumberExist(virtualAccount);
            if (!StringUtils.isEmpty(idNumber)){
                res.put(false, "该身份证已注册！");
                return res;
            }

            // 判断验证码是否正确且有效
            boolean valid = verificationCodeValidate(virtualAccount.getPhone(), virtualAccount.getVerificationCode());
            if (!valid){
                res.put(false, "验证码失效！");
                return res;
            }

            // 对登录密码和支付密码进行MD5加密
            String loginPwd = getMd5(virtualAccount.getLoginPwd());
            String payPwd = getMd5(virtualAccount.getPayPwd());
            virtualAccount.setLoginPwd(loginPwd);
            virtualAccount.setPayPwd(payPwd);

            // 尝试新增记录
            try {
                loginMapper.register(virtualAccount);
                VirtualAccount result = loginMapper.loginByUserName(virtualAccount);
                if (result != null){
                    res.put(true, "注册成功！");
                    return res;
                }
                res.put(false, "注册失败，未知错误！");
                return res;
            }catch (Exception e){
                e.printStackTrace();
                res.put(false, "未知错误！");
                return res;
            }
        }
        res.put(false, "信息未填充完整！");
        return res;
    }

    /**
     * @func 查询最近一次登录时间（业务实现）
     * @param virtualAccount
     * @return
     */
    @Override
    public String getLastLoginTime(VirtualAccount virtualAccount) {
        if (StringUtils.isEmpty(virtualAccount.getUserId())) return null;
        List<LoginRecord> res = loginMapper.getLastLoginTime(virtualAccount);
        if (res.size() != 2){
            return null;
        }else {
            return res.get(1).getLoginTime();
        }
    }
}
